
import numpy
import random
# https://zhuanlan.zhihu.com/p/120900436
'''
2048游戏核心逻辑，分析：
1. 以左移为基础，把4行的操作看成1行的操作。
2. 左移的操作，先把0全部移到行的末尾
3. 然后从行第一位开始，判断与后一位是否相等且不等0，若相等该位乘以2，删除后一位，末尾添加0
4. 右移操作是 行逆序--左移--再行逆序
5. 上移操作是 矩阵转置--左移--再转置
6. 下移操作是 矩阵转置--右移--再转置
'''
# 嵌套列表
matris = [[0 for i in range(4)]
          for i in range(4)]


def random_create():
    # 将矩阵中任意一个元素变为2或者4，2出现的概率大于4
    i, j = random.choice(range(4)), random.choice(range(4))
    if matris[i][j] == 0:
        matris[i][j] = 4 if random.randint(1, 100) > 70 else 2
    return matris


# 矩阵格式显示
def standard_print(matris):
    new_matris = numpy.array(matris)
    print(new_matris)


# 0移至末尾
def zeroToend(row):
    for i in range(len(row)-1, -1, -1):  # 倒序输出，步长为-1，输出到index为-1结束
        if row[i] == 0:
            row.pop(i)
            row.append(0)
    return row


# 移动合并
def merge(row):
    for i in range(len(row)-1):
        if row[i] == 0:
            break
        if row[i] == row[i+1]:
            row[i] *= 2
            row.pop(i+1)
            row.append(0)


# 矩阵倒置
def toTranspose(matris):
    for i in range(4):
        for j in range(i, 4):
            matris[i][j], matris[j][i] = matris[j][i], matris[i][j]


# 生成数字填充空位
def create_num(matris):
    emmpty_position = get_empty_position(matris)
    if not emmpty_position:
        return False
    row_index, col_index = random.choice(emmpty_position)
    matris[row_index][col_index] = 4 if random.randint(1, 10) == 1 else 2
    emmpty_position.remove((row_index, col_index))
    return matris


def left(matris):
    for row in matris:
        zeroToend(row)
        merge(row)
    create_num(matris)
    judge_win(matris)


def right(matris):
    for row in matris:
        row.reverse()
        zeroToend(row)
        merge(row)
        row.reverse()
    create_num(matris)
    judge_win(matris)


def up(matris):
    toTranspose(matris)
    for i in range(len(matris)):
        row = matris[i]
        zeroToend(row)
        merge(row)
    toTranspose(matris)
    create_num(matris)
    judge_win(matris)


def down(matris):
    toTranspose(matris)
    right(matris)
    toTranspose(matris)
    judge_win(matris)


# 获得空位坐标
def get_empty_position(matris):
    empty_position = []
    judge_gameOver(matris, empty_position)
    for i in range(len(matris)):
        for j in range(len(matris[i])):
            if matris[i][j] == 0:
                empty_position.append((i, j))
    return empty_position


def judge_win(matris):
    for i in matris:
        if 2048 in i:
            print('Congratulations on winning')
            return True
    return False


def judge_gameOver(matris, empty_position):
    for r in range(len(matris)):
        for c in range(len(matris[r])-1):
            # 判断是否可以移动
            if empty_position:
                print('可以移动')
                return False
            # 判断是否可以相加
            if matris[r][c] == matris[r][c+1] or matris[c][r] == matris[c+1][r]:
                return False
    print('Game Over!')
    return True


def main():
    matris = [[0 for i in range(4)]
              for i in range(4)]
    matris = create_num(matris)
    matris = create_num(matris)
    standard_print(matris)
    while True:
        inputName = input()
        if inputName == 'a':
            left(matris)
            standard_print(matris)
        elif inputName == 'd':
            right(matris)
            standard_print(matris)
        elif inputName == 'w':
            up(matris)
            standard_print(matris)
        elif inputName == 's':
            down(matris)
            standard_print(matris)
        else:
            print('Error input,try once again')


if __name__ == '__main__':
    # 控制台操作2048
    main()
